package com.hina.rec.application.service.system.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hina.rec.application.convert.system.RoleConvert;
import com.hina.rec.application.manager.system.MenuManager;
import com.hina.rec.application.manager.system.RoleManager;
import com.hina.rec.application.manager.system.RoleMenuManager;
import com.hina.rec.application.service.system.RoleService;
import com.hina.rec.common.model.IdReq;
import com.hina.rec.common.model.PageReq;
import com.hina.rec.common.utils.AssertUtil;
import com.hina.rec.domain.model.MenuDO;
import com.hina.rec.domain.model.RoleDO;
import com.hina.rec.domain.model.RoleMenuDO;
import com.hina.rec.endpoint.req.system.RoleSaveReq;
import com.hina.rec.endpoint.req.system.RoleUpdateReq;
import com.hina.rec.endpoint.res.base.PageRes;
import com.hina.rec.endpoint.res.system.RoleRes;
import com.hina.rec.endpoint.res.system.SimpleRoleRes;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 角色管理Service实现类
 *
 * @author liaosp
 * @date 2024-01-10
 */
@Service
@RequiredArgsConstructor
public class RoleServiceImpl implements RoleService {

    private final RoleManager roleManager;
    private final RoleMenuManager roleMenuManager;
    private final MenuManager menuManager;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(RoleSaveReq req) {
        // 检查数据是否存在
        RoleDO role = roleManager.lambdaQuery().eq(RoleDO::getRoleCode, req.getRoleCode())
                .one();
        AssertUtil.isNull(role, "角色已存在!");
        RoleDO roleDO = RoleConvert.INSTANCE.toRoleDO(req);
        // 保存实体对象
        roleManager.save(roleDO);
        saveOrUpdateRoleMenu(req.getMenuIds(), roleDO.getId(), false);
        return true;
    }

    @Override
    public boolean update(RoleUpdateReq req) {
        // 检查数据是否存在
        RoleDO role = roleManager.getById(req.getId());
        AssertUtil.notNull(role, "角色不存在");
        // 转换为实体对象并更新
        RoleDO roleDO = RoleConvert.INSTANCE.toRoleDO(req);
        roleManager.updateById(roleDO);
        saveOrUpdateRoleMenu(req.getMenuIds(), req.getId(), true);
        return true;
    }

    /**
     * 保存或更新角色菜单关系
     *
     * @param menuIds 菜单ID列表
     * @param roleId  角色ID
     * @param update  是否更新
     */
    private void saveOrUpdateRoleMenu(List<Integer> menuIds, Integer roleId, boolean update) {
        List<RoleMenuDO> roleMenuList = new ArrayList<>();
        for (Integer menuId : menuIds) {
            RoleMenuDO roleMenu = new RoleMenuDO();
            roleMenu.setRoleId(roleId);
            roleMenu.setMenuId(menuId);
            roleMenuList.add(roleMenu);
        }
        AssertUtil.notEmpty(roleMenuList, "菜单不能为空");
        if (update) {
            roleMenuManager.remove(roleMenuManager.lambdaQuery().eq(RoleMenuDO::getRoleId, roleId));
        }
        roleMenuManager.saveBatch(roleMenuList);
    }


    @Override
    public boolean delete(Integer id) {
        // 检查数据是否存在
        RoleDO role = roleManager.getById(id);
        AssertUtil.notNull(role, "角色不存在");
        return roleManager.removeById(id);
    }

    @Override
    public PageRes<RoleRes> page(PageReq req) {
        // 分页查询
        Page<RoleDO> page = new Page<>(req.getPageNum(), req.getPageSize());
        Page<RoleDO> rolePage = roleManager.page(page);
        // 转换为响应对象
        return PageRes.fromPage(rolePage, RoleConvert.INSTANCE::toRoleRes);
    }

    @Override
    public List<SimpleRoleRes> simpleList() {
        // 只查询启用状态的角色
        List<RoleDO> roleList = roleManager.lambdaQuery()
                // 状态为启用
                .eq(RoleDO::getStatus, true)
                .orderByAsc(RoleDO::getSort)
                .list();
        return RoleConvert.INSTANCE.toSimpleRoleResList(roleList);
    }

    @Override
    public List<RoleRes> list() {
        // 只查询启用状态的角色
        List<RoleDO> roleList = roleManager.lambdaQuery()
                // 状态为启用
                .eq(RoleDO::getStatus, true)
                .orderByAsc(RoleDO::getSort)
                .list();
        return RoleConvert.INSTANCE.toRoleResList(roleList);
    }

    @Override
    public RoleRes detail(IdReq req) {
        RoleDO role = roleManager.getById(req.getId());
        AssertUtil.notNull(role, "角色不存在");
        return RoleConvert.INSTANCE.toRoleRes(role);
    }

    @Override
    public List<Integer> menus(IdReq req) {
        // 检查角色是否存在
        RoleDO role = roleManager.getById(req.getId());
        AssertUtil.notNull(role, "角色不存在");

        // 查询角色关联的菜单ID列表
        List<RoleMenuDO> roleMenuList = roleMenuManager.lambdaQuery()
                .eq(RoleMenuDO::getRoleId, req.getId())
                .list();
        //只获取按钮启用的菜单
        List<Integer> ids = roleMenuList.stream()
                .map(RoleMenuDO::getMenuId)
                .toList();
        if (CollUtil.isEmpty(ids)) {
            return List.of();
        }
        return menuManager.lambdaQuery()
                .eq(MenuDO::getStatus, true)
//                .eq(MenuDO::getType, 3)
                .in(MenuDO::getId, ids)
                .list()
                .stream().map(MenuDO::getId).toList();
    }
}